package org.estela.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.TextArea;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.StringReader;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.estela.Version;
import org.estela.comp.EstelaCompiler;
import org.estela.comp.EstelaException;
import org.estela.comp.EstelaLexer;
import org.estela.comp.EstelaParser;
import org.estela.comp.EstelaProgram;
import org.estela.vm.EstelaVM;
import org.estela.vm.EstelaVMExcpetion;

import antlr.collections.AST;
import antlr.debug.misc.ASTFrame;

/**
 * 
 * @author antoniokantek
 * @version $Revision$
 */
public class EstelaFrame extends JFrame {
	private static final long serialVersionUID = 1L;

	private Log _log = LogFactory.getLog(getClass());
	
	private JMenuBar menuBar = new JMenuBar();

	private JMenu fileMenu = new JMenu(Version.getProperty(Version.MENU_FILE));
	private JMenuItem newMenuItem = new JMenuItem(Version
			.getProperty(Version.MENU_ITEM_NEW));
	private JMenuItem openMenuItem = new JMenuItem(Version
			.getProperty(Version.MENU_ITEM_OPEN));
	private JMenuItem saveMenuItem = new JMenuItem(Version
			.getProperty(Version.MENU_ITEM_SAVE));
	private JMenuItem saveAsMenuItem = new JMenuItem(Version
			.getProperty(Version.MENU_ITEM_SAVE_AS));
	
	private JMenuItem exitMenuItem = new JMenuItem(Version
			.getProperty(Version.MENU_ITEM_EXIT));

	private JMenu editMenu = new JMenu(Version.getProperty(Version.MENU_EDIT));
	private JMenuItem clearMenuItem = new JMenuItem(Version
			.getProperty(Version.MENU_ITEM_CLEAR));
	
	private JMenu runMenu = new JMenu(Version.getProperty(Version.MENU_RUN));
	private JMenuItem runMenuItem = new JMenuItem(Version
			.getProperty(Version.MENU_ITEM_RUN));
	private JMenuItem showASTMenuItem = new JMenuItem(Version
			.getProperty(Version.MENU_ITEM_SHOW_AST));

	private JMenu helpMenu = new JMenu(Version.getProperty(Version.MENU_HELP));
	private JMenuItem aboutMenuItem = new JMenuItem(Version
			.getProperty(Version.MENU_ITEM_ABOUT));

	private JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
	private JTextArea codeArea = new JTextArea();
	private JScrollPane scrollCode = new JScrollPane(codeArea);

	private JTextArea outArea = new JTextArea();
	private JScrollPane scrollOut = new JScrollPane(outArea);

	private EstelaVM _vm;

	public EstelaFrame(EstelaVM vm) {
		super(Version.getProperty(Version.FRAME_TITLE));
		_vm = vm;
		_vm._out = new PrintStream(
				new TextAreaOutputStream(this.outArea) );
		System.setOut(_vm._out);
		this.init();
	}

	private void init() {
		menuBar.add(fileMenu);
		fileMenu.add(newMenuItem);
		newMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent evt) {
				codeArea.setText("");
				
			}
			
		});
		fileMenu.add(openMenuItem);
		fileMenu.add(saveMenuItem);
		fileMenu.add(saveAsMenuItem);
		fileMenu.addSeparator();
		fileMenu.add(exitMenuItem);
		exitMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent evt) {
				System.exit(0);
			}
			
		});
		
		menuBar.add(editMenu);
		editMenu.add(clearMenuItem);
		clearMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent evt) {
				codeArea.setText("");
			}
			
		});
		
		menuBar.add(runMenu);
		runMenu.add(runMenuItem);
		runMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				String selectedText = codeArea.getSelectedText().trim();
			
				try {
					EstelaProgram program = EstelaCompiler.compile(selectedText);
					_vm.execute(program);

					
				} catch (EstelaException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (EstelaVMExcpetion e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		});
		
		runMenu.add(showASTMenuItem);
		showASTMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent evt) {
				try {
					String selectedText = codeArea.getSelectedText();
	
					EstelaLexer lexer = new EstelaLexer(new StringReader(selectedText));
					EstelaParser parser = new EstelaParser(lexer);
					parser.program();
	
					AST ast = parser.getAST();
					double d1 = 1.e3;
					
					ASTFrame astFrame = new ASTFrame("test", ast);
					astFrame.setSize(300,200);
					astFrame.setVisible(true);
				} catch (Exception ex) {
					ex.printStackTrace();
				}
			}
			
		});

		menuBar.add(helpMenu);
		helpMenu.add(aboutMenuItem);

		this.splitPane.add(scrollCode);
		this.splitPane.add(scrollOut);

		this.splitPane.setDividerLocation(200);

		this.setJMenuBar(menuBar);
		this.setLayout(new BorderLayout());
		this.add(splitPane, BorderLayout.CENTER);

		this.outArea.setText("Stella version "
				+ Version.getProperty(Version.getProperty(Version.VERSION))
				+ "\nDeveloped by Antonio Kantek (CVN Student)"
				+ "\nSpring"
				+ "\nFree Mem: " + Runtime.getRuntime().freeMemory() + "Kb");

		this.codeArea.setSelectedTextColor(Color.green);
		this.codeArea.addKeyListener(new KeyAdapter() {
			
			public void keyPressed(KeyEvent evt) {
				if (evt.getKeyCode() == KeyEvent.VK_CONTROL) {
					String selectedText = codeArea.getSelectedText();
					
					try {
						EstelaProgram program = EstelaCompiler.compile(selectedText);
						outArea.append("\n" + program.toString());
						
					} catch (EstelaException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		});
		
		// actions
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent evt) {
				System.exit(0);
			}
		});
	}

	/**
	 * 
	 */
	public static void main(String[] args) throws Throwable {
		Toolkit toolkit = java.awt.Toolkit.getDefaultToolkit();
		Dimension screenDim = toolkit.getScreenSize();
		int x = screenDim.width / 2;
		int y = screenDim.height / 2;
		
		EstelaVM vm = new EstelaVM();
		
		EstelaFrame frame = new EstelaFrame(vm);
		frame.setSize(640, 480);
		frame.setLocation(x - 320, y - 300);
		frame.setVisible(true);
	}
	

}
